package cn.com.pagoda.ideplugin.ui;

import cn.com.pagoda.ideplugin.service.TimeConversionService;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.table.JBTable;
import com.intellij.util.ui.JBUI;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * @author 曾庆苏 on 2023-05-06
 */
public class TimeConversionPanel {
    private final JPanel panel;
    private long unixTimestamp;
    private LocalDateTime localDateTime;
    private final TimeConversionService service;
    private List<String> timeZoneShowList;
    private String currentTimeZoneShow;
    private final JButton selectZoneBtn;
    private final JTextField nowText;
    private final JTextField milliText;
    private final JTextField secondText;
    private final JButton stopBtn;
    private final Timer timer;
    private final JTable table;

    public TimeConversionPanel(AnActionEvent anActionEvent, JPanel mainPanel) {
        this.service = new TimeConversionService();
        this.initData();
        panel = new JPanel(new GridBagLayout());
        panel.setSize(800, 800);
        addLabel("Time Zone Selection:", new Dimension(160, 25), createGrid(0, 0));
        selectZoneBtn = addButton(currentTimeZoneShow, new Dimension(150, 25), createGrid(0, 1));

        addLabel(">>Unix Timestamp Definition", new Dimension(190, 25), createGrid(1, 0,2));
        addLabel("The Current Local Time is:", new Dimension(180, 25), createGrid(2, 0));
        nowText = addTextField(false, new Dimension(160, 25), createGrid(2, 1));
        stopBtn = addButton("Pause", new Dimension(60, 25), createGrid(2, 2, 1, GridBagConstraints.NONE));
        addLabel("Current Unix Timestamp:", new Dimension(150, 25), createGrid(3, 0));
        secondText = addTextField(false, new Dimension(150, 25), createGrid(3, 1));
        addLabel("s", new Dimension(40, 25), createGrid(3, 2));
        milliText = addTextField(false, new Dimension(150, 25), createGrid(4, 1));
        addLabel("ms", new Dimension(40, 25), createGrid(4, 2));

        addLabel(">>Unix Timestamp(ms) To Local Time(yyyy-MM-dd HH:mm:ss)", new Dimension(400, 25), createGrid(5, 0, 3));
        JTextField inMilliText = addTextField(true, new Dimension(150, 25), createGrid(6, 0));
        JButton milliToLocal = addButton("Convert", new Dimension(80, 25), createGrid(6, 1, 1, GridBagConstraints.NONE));
        JTextField outLocalText = addTextField(false, new Dimension(160, 25), createGrid(6, 2));

        addLabel(">>Local Time(yyyy-MM-dd HH:mm:ss) To Unix Timestamp(ms)", new Dimension(400, 25), createGrid(7, 0, 3));
        JTextField inLocalText = addTextField(true, new Dimension(160, 25), createGrid(8, 0));
        JButton localToUnix = addButton("Convert", new Dimension(80, 25), createGrid(8, 1, 1, GridBagConstraints.NONE));
        JTextField outUnixText = addTextField(false, new Dimension(150, 25), createGrid(8, 2));

        addLabel(">>World Time Clock", new Dimension(150, 25), createGrid(9, 0));
        JButton reBtn = addButton("Refresh", new Dimension(80, 25), createGrid(9, 1, 1, GridBagConstraints.NONE));
        table = new JBTable();
        table.setDefaultEditor(Object.class, null);
        table.setCellSelectionEnabled(true);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        updateTable(table);
        JBScrollPane jbScrollPane = new JBScrollPane();
        jbScrollPane.setPreferredSize(new Dimension(150, 200));
        jbScrollPane.setViewportView(table);
        panel.add(jbScrollPane, createGrid(10, 0, 2, GridBagConstraints.HORIZONTAL));

        mainPanel.add(panel, getClass().getSimpleName());

        selectZoneBtn.addActionListener(e -> showTimeZonePopup());

        this.timer = new Timer(500, e -> timerRefresh());
        this.timer.start();

        stopBtn.addActionListener(e -> {
            if (timer.isRunning()) {
                timer.stop();
                stopBtn.setText("Resume");
            } else {
                timer.start();
                stopBtn.setText("Pause");
            }
        });

        localToUnix.addActionListener(e -> outUnixText.setText(service.localDateTimeStr2Milli(inLocalText.getText(), getTimeZone(currentTimeZoneShow))));

        milliToLocal.addActionListener(e -> outLocalText.setText(service.milli2LocalDateTimeStr(Long.parseLong(inMilliText.getText()), getTimeZone(currentTimeZoneShow))));

        reBtn.addActionListener(e -> updateTable(table));
    }

    private GridBagConstraints createGrid(int y, int x) {
        return createGrid(y, x, 1, GridBagConstraints.HORIZONTAL);
    }

    private GridBagConstraints createGrid(int y, int x, int w) {
        return createGrid(y, x, w, GridBagConstraints.HORIZONTAL);
    }

    private GridBagConstraints createGrid(int y, int x, int w, int fill) {
        GridBagConstraints c = new GridBagConstraints();
        c.gridy = y;
        c.gridx = x;
        c.gridwidth = w;
        c.weightx=0;
        c.weighty=0;
        c.fill = fill;
        c.insets = JBUI.insets(1);
        return c;
    }

    private void addLabel(String text, Dimension dimension, GridBagConstraints constraints) {
        JLabel label = new JLabel(text);
        label.setPreferredSize(dimension);
        panel.add(label, constraints);
    }

    private JButton addButton(String text, Dimension dimension, GridBagConstraints constraints) {
        JButton button = new JButton(text);
        button.setPreferredSize(dimension);
        panel.add(button, constraints);
        return button;
    }

    private JTextField addTextField(boolean editable, Dimension dimension, GridBagConstraints constraints) {
        JTextField textField = new JTextField();
        textField.setEditable(editable);
        textField.setPreferredSize(dimension);
        panel.add(textField, constraints);
        return textField;
    }

    /**
     * 时区下拉选择
     */
    private void showTimeZonePopup() {
        JBPopupFactory.getInstance().createListPopup(
                new BaseListPopupStep<>("Choose a time zone", timeZoneShowList) {
                    @Override
                    public PopupStep onChosen(String selectedValue, boolean finalChoice) {
                        selectZoneBtn.setText(selectedValue);
                        currentTimeZoneShow = selectedValue;
                        timerRefresh();
                        updateTable(table);
                        return super.onChosen(selectedValue, finalChoice);
                    }
                }
        ).showUnderneathOf(selectZoneBtn);
    }

    private void initData() {
        timeZoneShowList = Arrays.asList(
                "Asia/Shanghai",
                "Asia/Tokyo",
                "Asia/Singapore",
                "Asia/Bangkok",
                "Asia/Colombo",
                "Asia/Kabul",
                "Asia/Baghdad",
                "Asia/Dubai",
                "Europe/Moscow",
                "Europe/Paris",
                "Europe/Berlin",
                "Europe/London",
                "Europe/Dublin",
                "Europe/Istanbul",
                "Europe/Bucharest",
                "America/Los_Angeles",
                "America/New_York",
                "America/Lima",
                "America/Sao_Paulo",
                "Australia/Sydney",
                "Pacific/Auckland",
                "Africa/Nairobi",
                "Africa/Lagos");
        //初始化默认数据
        currentTimeZoneShow = timeZoneShowList.get(0);
        unixTimestamp = service.getUnixTimestamp();
        localDateTime = service.milli2LocalDateTime(unixTimestamp, getTimeZone(currentTimeZoneShow));
    }

    private void updateTable(JTable table) {
        DefaultTableModel model = new DefaultTableModel();
        String[] columnNames = {"Time Zone", "Time"};
        model.setColumnIdentifiers(columnNames);
        for (String value : timeZoneShowList) {
            model.addRow(new String[]{value, service.milli2LocalDateTimeStr(service.getUnixTimestamp(), getTimeZone(value))});
        }
        table.setModel(model);
    }

    private void timerRefresh() {
        unixTimestamp = service.getUnixTimestamp();
        localDateTime = service.milli2LocalDateTime(unixTimestamp, getTimeZone(currentTimeZoneShow));
        nowText.setText(service.getLocalDateTimeStr(localDateTime));
        milliText.setText(String.valueOf(unixTimestamp));
        secondText.setText(String.valueOf(unixTimestamp / 1000));
    }

    private String getTimeZone(String timeZoneShow) {
        return timeZoneShow;
    }
}